<template>
    <div class="menu-container" v-loading="loading">
        <!-- 面包导航 -->
        <el-breadcrumb separator="/" style="padding-left: 10px; padding-bottom: 10px; font-size: 12px">
            <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
            <el-breadcrumb-item>系统管理</el-breadcrumb-item>
            <el-breadcrumb-item>菜单管理</el-breadcrumb-item>
        </el-breadcrumb>

        <!-- 卡片主体 -->
        <el-card class="box-card" style="min-height: 580px">
            <div class="block">
                <!-- 节点过滤 -->
                <el-row :gutter="5">
                    <el-col :span="8">
                        <el-input size="small" placeholder="输入关键字进行过滤" v-model="filterText"> </el-input>
                    </el-col>
                    <el-col :span="2">
                        <el-button
                            size="small"
                            type="primary"
                            icon="el-icon-plus"
                            style="margin-left: 20px"
                            @click="openAddDialog()"
                            >父级</el-button
                        >
                    </el-col>
                    <el-col :span="2">
                        <el-button
                            size="small"
                            v-hasPermission="'menu:export'"
                            icon="el-icon-download"
                            @click="downExcel()"
                            >导出</el-button
                        >
                    </el-col>
                </el-row>

                <p>菜单权限树</p>
                <el-tree
                    :data="data"
                    accordion
                    :auto-expand-parent="false"
                    node-key="id"
                    show-checkbox
                    :default-expanded-keys="open"
                    :expand-on-click-node="false"
                    :render-content="renderContent"
                    :props="defaultProps"
                    highlight-current
                    :filter-node-method="filterNode"
                    ref="tree"
                ></el-tree>
            </div>
        </el-card>

        <!--    新增对话框   -->
        <el-dialog :title="addTitle" :visible.sync="addDialogVisible" width="40%">
            <el-form size="mini" ref="addFormRef" :model="addForm" label-width="80px" :rules="FormRules">
                <el-form-item label="节点名称" prop="menuName">
                    <el-input v-model="addForm.menuName"></el-input>
                </el-form-item>
                <el-form-item label="URL">
                    <el-input v-model="addForm.url"></el-input>
                </el-form-item>
                <el-form-item label="权限编码">
                    <el-input v-model="addForm.perms"></el-input>
                </el-form-item>
                <el-form-item label="图标">
                    <el-input v-model="addForm.icon"></el-input>
                </el-form-item>
                <el-form-item label="是否可用" prop="disabled">
                    <el-switch v-model="addForm.disabled" :active-value="false" :inactive-value="true"></el-switch>
                </el-form-item>
                <el-form-item label="是否展开" prop="open">
                    <template>
                        <el-radio v-model="addForm.open" label="1">展开</el-radio>
                        <el-radio v-model="addForm.open" label="0">关闭</el-radio>
                    </template>
                </el-form-item>
                <el-form-item label="排序" prop="orderNum" size="small">
                    <el-input-number v-model="addForm.orderNum" :min="1" :max="10" label="描述文字"></el-input-number>
                </el-form-item>
                <el-form-item label="类型" prop="type">
                    <template>
                        <el-radio v-model="addForm.type" label="0">菜单</el-radio>
                        <el-radio v-model="addForm.type" label="1">按钮</el-radio>
                    </template>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="addDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="addMenu">确 定</el-button>
            </div>
        </el-dialog>

        <!--    编辑对话框   -->
        <el-dialog :title="editTitle" :visible.sync="editDialogVisible" width="40%">
            <el-form size="mini" ref="editFormRef" :model="editForm" label-width="80px" :rules="FormRules">
                <el-form-item label="节点名称" prop="menuName">
                    <el-input v-model="editForm.menuName"></el-input>
                </el-form-item>
                <el-form-item label="URL">
                    <el-input v-model="editForm.url"></el-input>
                </el-form-item>
                <el-form-item label="权限编码">
                    <el-input v-model="editForm.perms"></el-input>
                </el-form-item>
                <el-form-item label="图标">
                    <el-input v-model="editForm.icon"></el-input>
                </el-form-item>
                <el-form-item label="是否可用" prop="disabled">
                    <el-switch v-model="editForm.disabled" :active-value="false" :inactive-value="true"></el-switch>
                </el-form-item>
                <el-form-item label="是否展开" prop="open">
                    <template>
                        <el-radio v-model="editForm.open" :label="1">展开</el-radio>
                        <el-radio v-model="editForm.open" :label="0">关闭</el-radio>
                    </template>
                </el-form-item>
                <el-form-item label="排序" prop="orderNum" size="small">
                    <el-input-number v-model="editForm.orderNum" :min="1" :max="10" label="描述文字"></el-input-number>
                </el-form-item>
                <el-form-item label="类型" prop="type">
                    <template>
                        <el-radio v-model="editForm.type" :label="0">菜单</el-radio>
                        <el-radio v-model="editForm.type" :label="1">按钮</el-radio>
                    </template>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="editDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="editMenu">确 定</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
let id = 1000;
import axios from "axios";
export default {
    name: "Menu",

    data() {
        return {
            loading: false,
            filterText: "", //节点过滤文本
            data: [], //菜单数据
            open: [], //默认展开的节点的 key 的数组
            defaultProps: {
                children: "children",
                label: "menuName",
            }, //节点变量名配置

            addTitle: "新增", //新增对话框标题
            editTitle: "编辑", //编辑对话框标题
            addDialogVisible: false, //新增节点对话框
            editDialogVisible: false, //编辑节点弹出框

            addForm: {
                parentId: "",
                menuName: "",
                url: "",
                type: "",
                orderNum: "",
                disabled: true,
                open: "",
                perms: "",
            },
            editForm: {}, //编辑节点表单数据

            FormRules: {
                menuName: [
                    { required: true, message: "节点名称不能为空", trigger: "blur" },
                    { min: 3, max: 10, message: "长度在 3 到 10 个字符", trigger: "blur" },
                ],
                disabled: [{ required: true, message: "节点状态不能为空", trigger: "blur" }],

                orderNum: [{ required: true, message: "排序不能为空", trigger: "blur" }],
                type: [{ required: true, message: "类型不能为空", trigger: "blur" }],
                open: [{ required: true, message: "是否展开不能为空", trigger: "blur" }],
            }, //添加表单验证规则
        };
    },

    watch: {
        filterText(val) {
            this.$refs.tree.filter(val); //监听查询输入框的数据
        },
    },

    created() {
        this.loading = true;
        this.getMenuTree();
        setTimeout(() => {
            this.loading = false;
        }, 500);
    },
    mounted() {},

    methods: {
        // 获取菜单树
        async getMenuTree() {
            const { data: res } = await this.$http.get("menu/tree");
            // console.log(res);
            if (res.code == 200) {
                this.data = res.data.tree;
                this.open = res.data.open;
            } else {
                return this.$message.error("获取菜单列表失败!");
            }
        },

        // 打开添加对话框
        openAddDialog(data) {
            //添加最高父级节点
            if (!data) {
                this.addTitle = "添加第一父级";
                this.addDialogVisible = true;
                this.addForm.parentId = 0;
            } else {
                this.addTitle = "添加节点 ：当前【" + data.menuName + "】";
                this.addDialogVisible = true;
                this.addForm.parentId = data.id;
            }
        },

        // 打开编辑对话框
        async openEditDialog(data) {
            this.editTitle = "编辑：【" + data.menuName + "】";
            const { data: res } = await this.$http.get("menu/edit/" + data.id);
            if (res.code == 200) {
                this.editForm = res.data;
                this.editDialogVisible = true;
            } else {
                return this.$message.error("节点编辑信息获取失败!");
            }
        },

        //导出Excel
        downExcel() {
            const res = axios
                .request({
                    url: "menu/excel",
                    method: "post",
                    responseType: "blob",
                })
                .then((res) => {
                    if (res.headers["content-type"] === "application/json") {
                        return this.$message.error("Subject does not have permission [role:export]");
                    }
                    const data = res.data;
                    let url = window.URL.createObjectURL(data); // 将二进制文件转化为可访问的url
                    const a = document.createElement("a");
                    document.body.appendChild(a);
                    a.href = url;
                    a.download = "菜单列表.xls";
                    a.click();
                    window.URL.revokeObjectURL(url);
                });
        },

        // 关键字过滤
        filterNode(value, data) {
            if (!value) return true;
            return data.menuName.indexOf(value) !== -1;
        },

        // 节点控制
        renderContent(h, { node, data, store }) {
            return (
                <span class="custom-tree-node">
                    <i class={data.icon}>
                        &nbsp;&nbsp;&nbsp;{node.label}
                        {node.data.type == 0 ? (
                            <el-tag style="margin-left:20px;" effect="plain" size="mini">
                                菜单
                            </el-tag>
                        ) : (
                            <el-tag style="margin-left:20px;" type="warning" effect="plain" size="mini">
                                权限 [{node.data.perms}]
                            </el-tag>
                        )}
                    </i>
                    <span>
                        <el-button
                            size="mini"
                            icon="el-icon-edit-outline"
                            type="text"
                            on-click={() => this.openEditDialog(data)}
                        >
                            编辑
                        </el-button>
                        <el-button
                            size="mini"
                            icon="el-icon-circle-plus-outline"
                            type="text"
                            on-click={() => this.openAddDialog(data)}
                        >
                            添加子节点
                        </el-button>
                        <el-button
                            size="mini"
                            icon="el-icon-delete"
                            type="text"
                            on-click={() => this.delMenu(node, data)}
                        >
                            删除
                        </el-button>
                    </span>
                </span>
            );
        },

        //添加菜单
        addMenu() {
            this.$refs.addFormRef.validate(async (valid) => {
                if (valid) {
                    const { data: res } = await this.$http.post("menu/add", this.addForm);
                    console.log(res);
                    if (res.code == 200) {
                        this.$notify.success({
                            title: "操作成功",
                            message: "节点添加成功",
                        });
                        this.addForm = {};
                        this.addDialogVisible = false;
                        this.getMenuTree();
                    }
                } else {
                    return this.$message.error("节点添加失败!");
                }
            });
        },

        // 编辑菜单
        editMenu() {
            this.$refs.editFormRef.validate(async (valid) => {
                if (valid) {
                    const { data: res } = await this.$http.put("menu/update/" + this.editForm.id, this.editForm);
                    if (res.code == 200) {
                        this.$notify({
                            title: "操作成功",
                            message: "节点基本信息已更新",
                            type: "success",
                        });
                        this.editForm = {};
                        this.getMenuTree();
                        this.editDialogVisible = false;
                    }
                } else {
                    return this.$message.error("节点信息更新失败!");
                }
            });
        },

        // 删除菜单
        delMenu(node, data) {
            this.$confirm("此操作将永久删除该节点, 是否继续?", "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
            })
                .then(async () => {
                    const { data: res } = await this.$http.delete("menu/delete/" + node.data.id);
                    // console.log(res);
                    if (res.code == 200) {
                        this.$message({
                            type: "success",
                            message: "删除成功!",
                        });
                        this.getMenuTree();
                    }
                })
                .catch(() => {
                    this.$message({
                        type: "info",
                        message: "已取消删除",
                    });
                });
        },
    },
};
</script>

<style lang="less">
.custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
}
</style>
